package com.dmx.net.transfer.impl;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.dmx.net.ConnectionException;
import com.dmx.net.HostInfoExtractor;
import com.dmx.net.NetworkProtocolClient;
import com.dmx.net.NotSupportedProtocolException;
import com.dmx.net.ftp.impl.RemoteFtpFileNotExistsException;

public class TransferCommand {

	private String postfix = ".storing";

	private boolean isResumed = false;

	private static final Log log = LogFactory.getLog(TransferCommand.class);

	private NetworkProtocolClient networkProtocolClient;

	public TransferCommand(NetworkProtocolClient networkProtocolClient) {
		this.networkProtocolClient = networkProtocolClient;
	}

	public TransferCommand(NetworkProtocolClient networkProtocolClient,
			boolean isResumed) {
		this.networkProtocolClient = networkProtocolClient;
		this.isResumed = isResumed;
	}

	public boolean putFile(File localFile, URL remoteFileUrl)
			throws NotSupportedProtocolException, ConnectionException,
			IOException {

		if (log.isInfoEnabled()) {
			log.info("begin to putfile: " + localFile.getAbsolutePath()
					+ " >> " + remoteFileUrl.toString());
		}

		try {

			HostInfoExtractor hinfoExtractor = new HostInfoExtractor(
					remoteFileUrl);

			String folder = hinfoExtractor.extractTheFolder();

			String fileName = hinfoExtractor.extractFileName();

			hinfoExtractor.decorateNetworkProtocolClient(networkProtocolClient);

			networkProtocolClient.safeLogin();

			if (!networkProtocolClient.navigateToFolder(folder)) {
				log.info("cannot navigateToFolder " + folder
						+ ", will have to create one");
				if (!networkProtocolClient.createRemoteFolder(folder)) {
					log.error("cannot createRemoteFolder: " + folder
							+ ", pls check the permission");
					return false;
				}

				if (!networkProtocolClient.navigateToFolder(folder)) {// and
					log.info("cannot navigateToFolder still," + folder
							+ ", just return");
					return false;
				}

			}

			return networkProtocolClient
					.putFile(localFile, fileName, isResumed);

		} finally {
			if (networkProtocolClient != null) {
				networkProtocolClient.close();
			}

		}

	}

	public boolean getFile(File localFile, URL remoteFileUrl)
			throws ConnectionException, IOException, MalformedURLException,
			NotSupportedProtocolException, RemoteFtpFileNotExistsException {
		File tempFile = null;

		if (log.isInfoEnabled()) {
			log.info("begin to getfile: " + remoteFileUrl.toString() + " >> "
					+ localFile.getAbsolutePath());
		}

		if (isResumed == true) {
//			tempFile = new File(localFile.getAbsolutePath() + postfix);
			tempFile = new File(localFile.getAbsolutePath());
		}

		try {

			HostInfoExtractor hinfoExtractor = new HostInfoExtractor(
					remoteFileUrl);

			String folder = hinfoExtractor.extractTheFolder();

			String fileName = hinfoExtractor.extractFileName();

			hinfoExtractor.decorateNetworkProtocolClient(networkProtocolClient);

			networkProtocolClient.safeLogin();

			if (!networkProtocolClient.navigateToFolder(folder)) {
				return false;
			}

			if (tempFile != null) {// resume download
				boolean isSuccess = networkProtocolClient.getFile(tempFile, fileName, true);

				if(isSuccess) {
					if (true == tempFile.renameTo(localFile)) {
						return true;
					} else {
						log.error("Failed to rename from:"
								+ tempFile.getAbsolutePath() + " to: "
								+ localFile.getAbsolutePath());
					}
	
					return false;
				} else
					return false;

			} else {// don't resume download
				return networkProtocolClient
						.getFile(localFile, fileName, false);
			}

		} finally {
			if (networkProtocolClient != null)
				networkProtocolClient.close();
		}
	}

	public boolean deleteFile(String destName) throws ConnectionException {
		try {
			networkProtocolClient.safeLogin();
			return networkProtocolClient.deleteResource(destName);
		}  finally {
			if (networkProtocolClient != null)
				networkProtocolClient.close();
		}
		
	}
	
	public boolean isResumed() {
		return isResumed;
	}

	public void setResumed(boolean isResumed) {
		this.isResumed = isResumed;
	}

	public String getPostfix() {
		return postfix;
	}

	public void setPostfix(String postfix) {
		this.postfix = postfix;
	}

	public NetworkProtocolClient getNetworkProtocolClient() {
		return networkProtocolClient;
	}

}
